#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/sm2.h>
#include <gmssl/pem.h>
#include <gmssl/error.h>
#include <gmssl/sm3.h>

int main(int argc, char **argv)
{
    if (argc != 4) {
        printf("Usage: %s <private_key.pem> <input.txt> <signature.sig>\n", argv[0]);
        return 1;
    }

    const char *private_key_file = argv[1];
    const char *input_file = argv[2];
    const char *signature_file = argv[3];

    SM2_KEY sm2_key;
    FILE *key_fp = NULL;
    FILE *input_fp = NULL;
    FILE *sig_fp = NULL;
    unsigned char dgst[32];
    unsigned char sig[SM2_MAX_SIGNATURE_SIZE];
    size_t siglen;
    unsigned char buffer[1024];
    size_t len;

    // 加载私钥
    key_fp = fopen(private_key_file, "r");
    if (!key_fp) {
        perror("Failed to open private key file");
        return 1;
    }

    // 使用 PEM 格式加载私钥
    if (sm2_private_key_info_from_pem(&sm2_key, key_fp) != 1) {
        fprintf(stderr, "Failed to read private key from PEM\n");
        fclose(key_fp);
        return 1;
    }
    fclose(key_fp);

    // 读取输入文件并计算SM3哈希
    input_fp = fopen(input_file, "r");
    if (!input_fp) {
        fprintf(stderr, "Error opening input file: %s\n", input_file);
        return 1;
    }

    SM3_CTX sm3_ctx;
    sm3_init(&sm3_ctx);

    while ((len = fread(buffer, 1, sizeof(buffer), input_fp)) > 0) {
        sm3_update(&sm3_ctx, buffer, len);
    }
    fclose(input_fp);

    sm3_finish(&sm3_ctx, dgst);

    // 生成签名
    siglen = sizeof(sig);  // 确保我们为签名的大小传递正确的变量
    if (sm2_sign(&sm2_key, dgst, sig, &siglen) != 1) {
        fprintf(stderr, "Error generating SM2 signature\n");
        return 1;
    }

    // 写入签名到文件
    sig_fp = fopen(signature_file, "wb");
    if (!sig_fp) {
        fprintf(stderr, "Error opening signature file: %s\n", signature_file);
        return 1;
    }

    if (fwrite(sig, 1, siglen, sig_fp) != siglen) {
        fprintf(stderr, "Error writing signature to file: %s\n", signature_file);
        fclose(sig_fp);
        return 1;
    }
    fclose(sig_fp);

    printf("Signature generated and saved to %s\n", signature_file);
    return 0;
}
